// Copyright 2006-2007 Deutsches Forschungszentrum fuer Kuenstliche Intelligenz
// or its licensors, as applicable.
//
// You may not use this file except under the terms of the accompanying license.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You may
// obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Project: ocr-bpnet - neural network classifier
// File: bpnet-line.cc
// Purpose: ppnet line recognizer
// Responsible: Hagen Kaprykowsky
// Reviewer:
// Primary Repository:
// Web Sites: www.iupr.org, www.dfki.de, www.ocropus.org

#include "colib.h"
#include "imgio.h"
#include "langmod-shortest-path.h"
#include "bengali.h"
#include "ocr-utils.h"
#include "ocrcomponents.h"
#include "bpnetline.h"
#include "dgraphics.h"

using namespace ocropus;
using namespace imgio;
using namespace colib;

bool is_bangla_early_vowel_char(nuchar &character) {
    int value = character.ord();
    if (0x09bf == value || 0x09c7 == value || 0x09c8 == value) {
        return true;
    }
    return false;
}

bool is_bangla_consonant_char(nuchar &character) {
    int value = character.ord();
    if (value < 0x0995 || value > 0x09b9) {
        return false;
    }
    if (0x09a9 == value || 0x09b1 == value || 0x09b3 == value
       || 0x09b4 == value || 0x09b5 == value) { // reserved values
        return false;
    }
    return true;
}

bool is_bangla_combining_char(nuchar &character) {
    switch(character.ord()) {
        case 0x0981: // chandra bindu
        case 0x0982: // anusvara
        case 0x0983: // visarga
        case 0x09bc: // nukta
        case 0x09be: // aa kar
        case 0x09bf: // i kar
        case 0x09c0: // ii kar
        case 0x09c1: // u kar
        case 0x09c2: // uu kar
        case 0x09c3: // vocalic r kar
        case 0x09c4: // vocalic rr kar
        case 0x09c7: // e kar
        case 0x09c8: // ai kar
        case 0x09cb: // o kar
        case 0x09cc: // au kar
        case 0x09cd: // virama
        case 0x09d7: // au length mark?
        case 0x09e2: // vocalic l kar
        case 0x09e3: // vocalic ll kar
            return true;
    }
    return false;
}

void fix_bangla_string(nustring &result) {
    int length;
    nustring tmpstr;
    nuchar tmpchar;
    int i, j;
    int value;
    length = result.length();
    for(i = 0; i < length; i++) {
        if(0x0985 == result[i].ord() && 0x09be == result[i+1].ord()) { //letter aa
            tmpstr.push(nuchar(0x0986));
            i++;
        } else if(is_bangla_early_vowel_char(result[i])) { // early vowels
            if(is_bangla_consonant_char(result[i + 1])) { // vowels must attach to consonants
                bool found_two_part = false;
                tmpstr.push(result[i+1]);
                if (result[i].ord() == 0x09c7) { // e kar might mean o or au
                    for(j = i + 2;
                        j < length
                        && is_bangla_combining_char(result[j])
                        && !found_two_part; 
                        j++) {
                        if(result[j].ord() == 0x09be) { // found an o
                            tmpstr.push(nuchar(0x09cb));
                            found_two_part = true;
                        } else if(result[j].ord() == 0x09d7) { // found an au
                            tmpstr.push(nuchar(0x09cc));
                            found_two_part = true;
                        }
                    }
                    if (!found_two_part) { // no o or au means it was just an e
                        tmpstr.push(nuchar(result[i]));
                    }
                } else {
                    tmpstr.push(result[i]);
                }
                i++;
                while(i + 1 < length && is_bangla_combining_char(result[i + 1])) {
                    value = result[i + 1].ord();
                    // only push aa kar if we didn't previously push o or au
                    if (!found_two_part || (0x09be != value && 0x09d7 != value)) {
                        tmpstr.push(result[i + 1]);
                    }
                    i++;
                }
            }
        } else if(is_bangla_consonant_char(result[i])) {
            tmpstr.push(result[i]);
            // push combining chars
            while(i + 1 < length && is_bangla_combining_char(result[i + 1])) {
                tmpstr.push(result[i + 1]);
                i++;
            }
        } else if(!is_bangla_combining_char(result[i])) {
            tmpstr.push(result[i]);
        }
    }
    copy(result, tmpstr);
}

int main(int argc,char **argv) {

    try {
        if(argc!=3) throw "usage ... bpnet-file input.png";

        autodel<ISegmentLine> segmenter(make_SegmentLineByProjection());
        autodel<IRecognizeLine> lineocr(make_NewBpnetLineOCR(argv[1]));
        autodel<ICharLattice> lattice(make_ShortestPathCharLattice());

        bytearray image;
        read_image_gray(image,argv[2]);
        make_page_black(image);

        intarray segmentation;
        segmenter->charseg(segmentation,image);

        idmap components;
        lineocr->recognizeLine(*lattice,components,segmentation,image);

        nustring result;
        lattice->bestpath(result);

        //fix_bangla_string(result);

        if(result.length()<1) {
            fprintf(stderr,"no result\n");
            return 1;
        } else {
            char *resultptr = result.mallocUtf8Encode();
            printf("%s\n", resultptr);
            free(resultptr);
        }

        /*dinit(800,600);
        dshow(image, "y");
        dshowr(segmentation, "Y");
        dwait();*/
    }
    catch(const char *oops) {
        fprintf(stderr,"oops: %s\n",oops);
    }
    return 0;
}

